package com.example.demo.service;

import com.aliyun.auth.credentials.Credential;
import com.aliyun.auth.credentials.provider.StaticCredentialProvider;
import com.aliyun.sdk.service.dyvmsapi20170525.AsyncClient;
import com.aliyun.sdk.service.dyvmsapi20170525.models.QueryCallDetailByCallIdRequest;
import com.aliyun.sdk.service.dyvmsapi20170525.models.QueryCallDetailByCallIdResponse;
import com.aliyun.sdk.service.dyvmsapi20170525.models.SingleCallByTtsRequest;
import com.aliyun.sdk.service.dyvmsapi20170525.models.SingleCallByTtsResponse;

import com.example.demo.config.AlibabaCloudConfig;
import com.example.demo.config.AliyunConfig;
import com.example.demo.config.DurationTypeAdapter;
import com.example.demo.model.dto.SingleCallByTtsRequestDTO;
import com.google.gson.*;

import darabonba.core.client.ClientOverrideConfiguration;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.concurrent.CompletableFuture;

@Service
@Slf4j
public class DyvmsService {
    private final AlibabaCloudConfig alibabaCloudConfig; // 阿里云通用配置
    private final AliyunConfig aliyunConfig; // 阿里云语音服务特定配置

    private final Gson gson;

    public DyvmsService(AlibabaCloudConfig alibabaCloudConfig, AliyunConfig aliyunConfig) {
        this.alibabaCloudConfig = alibabaCloudConfig;
        this.aliyunConfig = aliyunConfig;

        // 创建支持 Duration 的 Gson 实例
        this.gson = new GsonBuilder()
                .registerTypeAdapter(Duration.class, new DurationTypeAdapter())
                .create();
    }

    /**
     * 使用语音合成技术进行单次语音呼叫
     * @param requestDTO  包含被叫号码等信息的请求DTO对象
     * @return  阿里云语音服务返回的JSON响应字符串
     * @throws Exception  可能抛出的异常
     */
    public String singleCallByTts(SingleCallByTtsRequestDTO requestDTO) throws Exception {
        try (AsyncClient client = createClient()) { // 使用try-with-resources确保客户端资源被正确关闭
            SingleCallByTtsRequest singleCallByTtsRequest = SingleCallByTtsRequest.builder()
                    .calledShowNumber(aliyunConfig.getDyvms().getCalledShowNumber()) // 设置主叫号码显示
                    .calledNumber(requestDTO.getCalledNumber()) // 设置被叫号码 (从请求DTO获取)
                    .ttsCode(aliyunConfig.getDyvms().getTtsCode()) // 设置语音合成代码
                    .build();

            CompletableFuture<SingleCallByTtsResponse> response = client.singleCallByTts(singleCallByTtsRequest); // 异步发送请求
            SingleCallByTtsResponse resp = response.get(); // 获取异步操作的结果

            return this.gson.toJson(resp); // 将响应对象转换为JSON字符串
        }
    }

    /**
     * 创建阿里云语音服务异步客户端
     * @return 阿里云语音服务异步客户端
     */
    private AsyncClient createClient() {
        StaticCredentialProvider provider = StaticCredentialProvider.create(Credential.builder() // 创建静态凭证提供者
                .accessKeyId(alibabaCloudConfig.getAccessKeyId()) // 设置AccessKeyId
                .accessKeySecret(alibabaCloudConfig.getAccessKeySecret()) // 设置AccessKeySecret
                .build());

        return AsyncClient.builder() // 创建异步客户端
                .region("cn-shenzhen") // 设置地域
                .credentialsProvider(provider) // 设置凭证提供者
                .overrideConfiguration( // 设置客户端配置覆盖
                        ClientOverrideConfiguration.create()
                                .setEndpointOverride("dyvmsapi.aliyuncs.com") // 设置API网关地址
                )
                .build();
    }

    /**
     * 查询指定通话的呼叫详情
     * @param callId 通话ID
     * @return 呼叫详情的JSON字符串
     */
    public String queryCallDetail(String callId) throws Exception {
        try (AsyncClient client = createClient()) {
            // 构建查询请求
            QueryCallDetailByCallIdRequest request = QueryCallDetailByCallIdRequest.builder()
                    .callId(callId)
                    .prodId(11000000300006L) // 语音通知产品ID
                    .queryDate(System.currentTimeMillis()) // 当前时间戳（毫秒）
                    .build();

            log.info("【语音通知】发起查询通话详情请求, CallId: {}, 请求参数: {}",
                    callId, this.gson.toJson(request));

            // 发送异步请求
            CompletableFuture<QueryCallDetailByCallIdResponse> response = client.queryCallDetailByCallId(request);

            // 获取响应结果
            QueryCallDetailByCallIdResponse resp = response.get();

            // 记录完整响应
            String responseJson = this.gson.toJson(resp);
            log.info("【语音通知】查询通话详情响应, CallId: {}, 响应内容: {}",
                    callId, responseJson);

            return responseJson;
        } catch (Exception e) {
            log.error("查询通话详情失败, CallId: {}, 错误信息: {}", callId, e.getMessage());
            throw e;
        }
    }

    /**
     * 检查通话是否接通（基于通话详情）
     * @param callId 通话ID
     * @return 是否接通
     */
    public boolean checkCallConnected(String callId) {
        try {
            String detailJson = queryCallDetail(callId);
            log.info("【语音通知】开始解析通话详情, CallId: {}, 详情数据: {}", callId, detailJson);

            // 解析整个响应
            JsonObject response = JsonParser.parseString(detailJson).getAsJsonObject();

            // 检查状态码
            if (response.get("statusCode").getAsInt() != 200) {
                log.warn("【语音通知】HTTP响应状态码不是200, CallId: {}", callId);
                return false;
            }

            // 获取body对象
            JsonObject body = response.getAsJsonObject("body");
            if (body == null) {
                log.warn("【语音通知】响应中没有body字段, CallId: {}", callId);
                return false;
            }

            // 检查响应码
            String code = body.get("code").getAsString();
            if (!"OK".equals(code)) {
                log.warn("【语音通知】查询通话详情失败, CallId: {}, 响应code: {}", callId, code);
                return false;
            }

            // 解析data字符串为JSON对象
            String dataStr = body.get("data").getAsString();
            JsonObject data = JsonParser.parseString(dataStr).getAsJsonObject();
            log.info("【语音通知】解析后的 data 对象: {}", data);

            // 检查通话状态
            String state = data.get("state").getAsString();
            int duration = data.get("duration").getAsInt();

            // 判断通话是否接通的逻辑
            boolean isConnected = false;

            // 通话时长大于0或状态码为502表示接通
            if (duration > 0 || "502".equals(state)) {
                isConnected = true;
            } else if ("200".equals(state)) {
                // 状态200表示外呼任务提交成功，但未必接通
                isConnected = false;
            }

            log.info("【语音通知】通话状态检查结果: {}, 状态码: {}, 通话时长: {}秒, CallId: {}",
                    isConnected ? "已接通" : "未接通", state, duration, callId);

            return isConnected;

        } catch (Exception e) {
            log.error("检查通话状态失败, CallId: {}, 错误信息: {}", callId, e.getMessage(), e);
            return false;
        }
    }
}